package com.xy.xymall.search.thread;

import java.util.concurrent.*;

/**
 * @author XY
 * @date 2020/10/8 15:26
 * 线程测试类
 */
public class ThreadTest {
    public static ExecutorService executorService=Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建异步任务
        System.out.println("main..start....");
//        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//            System.out.println("当前线程:" + Thread.currentThread().getName());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//        }, executorService);
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程:" + Thread.currentThread().getName());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executorService).whenCompleteAsync((result,exception) -> {
//            //whenCompleteAsync：异步执行，虽然能得到异常信息，但是没法修改返回数据。
//            System.out.println("异步任务成功"+result);
//        }).exceptionally(throwable -> {
//            //可以感知异常，同时返回默认值
//            return 10;
//        });

        /**
         *
         * 方法完成后的处理，不论是失败还是成功
         */
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程:" + Thread.currentThread().getName());
//            int i = 10 / 0;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executorService).handle((result, throwable) -> {
//            if(result!=null){
//                return result*2;
//            }
//            if(throwable!=null){
//                return 0;
//            }
//            return 1;
//        });
        /**
         * 线程串行化
         * 1、thenRun:不能获取到上一步的执行结果
         * 2、thenAccept：能接受上一步结果，但是无返回值
         */
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程:" + Thread.currentThread().getName());
//            int i = 10 / 2;
//            System.out.println("运行结果：" + i);
//            return i;
//        }, executorService).thenApplyAsync(res -> {
//            System.out.println("任务2启动了" + res);
//            return 1;
//        }, executorService);

        /**
         * 两任务组合-都要完成
         */
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getName());
            int i = 10 / 2;
            System.out.println("任务1结果：" + i);
            return i;
        }, executorService);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getName());
            System.out.println("任务2结果");
            return "hello";
        }, executorService);

//        future1.runAfterBothAsync(future2,()-> {
//            System.out.println("任务3开始");
//        },executorService);

//        future1.thenAcceptBothAsync(future2,(f1,f2)-> {
//            System.out.println("任务3开始："+f1+":"+f2);
//        },executorService);

        CompletableFuture<String> stringCompletableFuture = future1.thenCombineAsync(future2, (f1, f2) -> {
            return f1 + ":" + f2 + "::haha";
        }, executorService);

        /**
         * 两任务组合-一个完成
         */


        System.out.println("main..end...."+stringCompletableFuture.get());
    }

    public static void thread(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main..start....");
        /**
         *        1、继承Thread
         *        new Thread01().start();
         *        2、实现Runnable
         *        new Thread(new Thread02()).start();
         *        3、实现Callable接口+FutureTask(可以拿到返回结果，可以处理异常)
         *        FutureTask<Integer> task=new FutureTask<Integer>(new Thread03());
         *        new Thread(task).start();
         *        等待整个线程执行完成，获取返回结果
         *        Integer integer = task.get();
         *        4、线程池，一般要保证当前系统中池只有一两个，每个异步任务直接提交给线程池让它自己运行
         *        区别：1、2不能得到返回值，3可以拿到返回值，1、2、3都不能控制资源，4可以控制资源，性能是稳定的
         *        创建：1、ExecutorService executorService=Executors.newFixedThreadPool(10);
         *                          executorService.execute(new Thread02());
         *             2、 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor();
         *             线程池七大参数：
         *             （1）corePoolSize：线程池中常驻核心线程数，创建好后就准备就绪，等待接收异步任务执行（一直存在，除非allowCoreThreadTimeOut）
         *             （2）maximumPoolSize：线程池能够容纳同时执行的最大线程数，此值必须大于等于1，控制资源并发
         *             （3）keepAliveTime：多余的空闲线程存活时间。当前线程池数量超过corePoolSize时，当空闲时间到达keepAliveTime值时，多余空闲线程会被销毁直到只剩下corePoolSize个线程为止。
         *             （4）unit：keepAliveTime的时间单位
         *             （5）workQueue：任务队列，被提交但尚未执行的任务，只要有空闲的线程，就会去队列里面取出新的任务执行
         *             （6）threadFactory：表示生成线程池中的工作线程的线程工厂，用于创建线程，一般为默认线程工厂即可
         *             （7）handler：拒绝策略，表示当队列满了并且工作线程大于等于线程池的最大线程数（maximumPoolSize）时如何来拒绝来请求的Runnable的策略
         *        工作顺序：
         *      当线程池中线程数小于corePoolSize时，新提交任务将创建一个新线程执行任务，即使此时线程池中存在空闲线程。
         *      当线程池中线程数达到corePoolSize时，新提交任务将被放入workQueue中，等待线程池中任务调度执行 。
         *      当workQueue已满，且maximumPoolSize > corePoolSize时，新提交任务会创建新线程执行任务，最大数量为maximumPoolSize。
         *      当workQueue已满，且提交任务数超过maximumPoolSize，任务由RejectedExecutionHandler处理。
         *      max都执行完成，有很多空闲，当线程池中线程数超过corePoolSize，且超过这部分的空闲时间达到keepAliveTime时，回收这些线程。
         *      当设置allowCoreThreadTimeOut(true)时，线程池中corePoolSize范围内的线程空闲时间达到keepAliveTime也将回收。
         *
         *      一个线程池，core:7,  max:20  queue:50  100并发怎么分配
         *      7个立即执行，50个会进入队列，队列满了之后，会再开13个线程执行，剩下30个拒绝
         *
         *      Future类:可以获取到异步结果
         */
//        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor();
        System.out.println("main...end...");

    }

    public static class Thread01 extends Thread{
        @Override
        public void run(){
            System.out.println("当前线程:"+Thread.currentThread().getName());
            int i=10/2;
            System.out.println("运行结果："+i);
        }
    }

    public static class Thread02 implements Runnable{
        @Override
        public void run() {
            System.out.println("当前线程:"+Thread.currentThread().getName());
            int i=10/2;
            System.out.println("运行结果："+i);
        }
    }

    public static class Thread03 implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程:"+Thread.currentThread().getName());
            int i=10/2;
            System.out.println("运行结果："+i);
            return i;
        }
    }
}
